package com.xx.executor.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.xx.common.pojo.XxlJobInfo;
import com.xx.executor.core.cron.CronExpression;
import com.xx.executor.mapper.XxlJobInfoDao;
import com.xx.common.api.XxlJobService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;

import javax.annotation.Resource;
import java.util.Date;

/**
 * core job action for xxl-job
 *
 * @author xuxueli 2016-5-28 15:30:33
 */
@DubboService
@Slf4j
public class XxlJobServiceImpl implements XxlJobService {


    @Resource
    private XxlJobInfoDao xxlJobInfoDao;

    /**
     * add job
     *
     * @param jobInfo 任务
     * @return 新增结果
     */
    @Override
    public Boolean add(XxlJobInfo jobInfo) throws Exception {

        // valid base
        validParam(jobInfo);
        // add in db
        jobInfo.setAddTime(new Date());
        jobInfo.setUpdateTime(new Date());
        jobInfo.setGlueUpdatetime(new Date());
        xxlJobInfoDao.save(jobInfo);
        return jobInfo.getId() >= 1;
    }


    /**
     * 根据执行器任务handler修改任务
     *
     * @param jobInfo 任务
     * @return 修改结果
     */
    @Override
    public Boolean update(XxlJobInfo jobInfo) throws Exception {

        // valid base
        validParam(jobInfo);
        // add in db
        jobInfo.setAddTime(new Date());
        jobInfo.setUpdateTime(new Date());
        jobInfo.setGlueUpdatetime(new Date());
        int update = xxlJobInfoDao.update(jobInfo);
        return update >= 1;
    }

    /**
     * remove job
     * *
     *
     * @param executorHandler 执行任务标识
     * @return 移除结果
     */
    @Override
    public Boolean remove(String executorHandler) throws Exception {
        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadByExecutorHandler(executorHandler);
        if (xxlJobInfo == null) {
            throw new Exception("没有找到对应的任务!");
        }
        int delete = xxlJobInfoDao.delete(executorHandler);
        return delete >= 1;
    }

    /**
     * start job
     *
     * @param executorHandler 执行任务标识
     * @return 开启结果
     */
    @Override
    public Boolean start(String executorHandler) throws Exception {
        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadByExecutorHandler(executorHandler);

        // valid
        //ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(xxlJobInfo.getScheduleType(), ScheduleTypeEnum.NONE);
        if ("NONE ".equals(xxlJobInfo.getScheduleType())) {
            throw new Exception("该任务的调度类型为none!");
        }

        // next trigger time (5s后生效，避开预读周期)
        long nextTriggerTime = 0;
        /*try {
            Date nextValidTime = JobScheduleHelper.generateNextValidTime(xxlJobInfo, new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS));
            if (nextValidTime == null) {
                throw new Exception("下一次校验时间为null");
            }
            nextTriggerTime = nextValidTime.getTime();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw e;
        }*/

        xxlJobInfo.setTriggerStatus(1);
        xxlJobInfo.setTriggerLastTime(0);
        xxlJobInfo.setTriggerNextTime(nextTriggerTime);

        xxlJobInfo.setUpdateTime(new Date());
        int update = xxlJobInfoDao.update(xxlJobInfo);
        return update >= 1;
    }

    /**
     * stop job
     *
     * @param executorHandler 执行任务标识
     * @return 暂停结果
     */
    @Override
    public Boolean stop(String executorHandler) throws Exception {
        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadByExecutorHandler(executorHandler);

        xxlJobInfo.setTriggerStatus(0);
        xxlJobInfo.setTriggerLastTime(0);
        xxlJobInfo.setTriggerNextTime(0);
        xxlJobInfo.setUpdateTime(new Date());
        int update = xxlJobInfoDao.update(xxlJobInfo);
        return update >= 1;
    }

    /**
     * 参数校验
     *
     * @param jobInfo 任务
     * @throws Exception 错误信息
     */
    public void validParam(XxlJobInfo jobInfo) throws Exception {
        if (jobInfo.getJobDesc() == null || jobInfo.getJobDesc().trim().length() == 0) {
            throw new Exception("请输入任务描述!");
        }
        if (jobInfo.getAuthor() == null || jobInfo.getAuthor().trim().length() == 0) {
            throw new Exception("请输入任务作者!");
        }

        // valid trigger
        //ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null);
        if (ObjectUtil.isEmpty(jobInfo.getScheduleType())) {
            throw new Exception("请输入调度类型!");
        }
        if ("CRON".equals(jobInfo.getScheduleType())) {
            if (jobInfo.getScheduleConf() == null || !CronExpression.isValidExpression(jobInfo.getScheduleConf())) {
                throw new Exception("请输入正确的cron表达式!");
            }
        } else if ("FIX_RATE".equals(jobInfo.getScheduleType())) {
            if (jobInfo.getScheduleConf() == null) {
                throw new Exception("您选择的调度类型未固定速度,请输入固定速度值!");
            }
            try {
                int fixSecond = Integer.valueOf(jobInfo.getScheduleConf());
                if (fixSecond < 1) {
                    throw new Exception("固定速度值必须大于等于1!");
                }
            } catch (Exception e) {
                throw new Exception("固定速度值必须为Integer类型!");
            }
        }

        // valid job
        if (ObjectUtil.isEmpty(jobInfo.getGlueType())) {
            throw new Exception("没有匹配到该运行模式!");
        }
        if ("BEAN".equals(jobInfo.getGlueType()) && (jobInfo.getExecutorHandler() == null || jobInfo.getExecutorHandler().trim().length() == 0)) {
            throw new Exception("请输入执行器任务handler!");
        }
        // 》fix "\r" in shell
        if ("GLUE_SHELL".equals(jobInfo.getGlueType()) && jobInfo.getGlueSource() != null) {
            jobInfo.setGlueSource(jobInfo.getGlueSource().replaceAll("\r", ""));
        }

        // valid advanced
        if (ObjectUtil.isEmpty(jobInfo.getExecutorRouteStrategy())) {
            throw new Exception("请输入正确的执行器路由策略!");
        }
        if (ObjectUtil.isEmpty(jobInfo.getMisfireStrategy())) {
            throw new Exception("请输入正确的调度过期策略!");
        }
        if (ObjectUtil.isEmpty(jobInfo.getExecutorBlockStrategy())) {
            throw new Exception("请输入正确的阻塞处理策略!");
        }

        // 子任务处理关闭
		/*if (jobInfo.getChildJobId()!=null && jobInfo.getChildJobId().trim().length()>0) {
			String[] childJobIds = jobInfo.getChildJobId().split(",");
			for (String childJobIdItem: childJobIds) {
				if (childJobIdItem!=null && childJobIdItem.trim().length()>0 && isNumeric(childJobIdItem)) {
					XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem));
					if (childJobInfo==null) {
						return new ReturnT<String>(ReturnT.FAIL_CODE,
								MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem));
					}
				} else {
					return new ReturnT<String>(ReturnT.FAIL_CODE,
							MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem));
				}
			}

			// join , avoid "xxx,,"
			String temp = "";
			for (String item:childJobIds) {
				temp += item + ",";
			}
			temp = temp.substring(0, temp.length()-1);

			jobInfo.setChildJobId(temp);
		}*/
    }

}
